#pragma once
#include <iostream>
#include <pthread.h>
#include <string>
#include <functional>
#include <cassert>
#define NUM 1024
class Thread;//声明一下
class Context//线程上下文类
{
public:
    Context()
    :_this(nullptr)
    ,_args(nullptr)
    {}
    ~Context()
    {}
public:
    Thread* _this;
    void* _args;
};
class Thread
{
public:
    typedef std::function<void*(void*)> func_t;//定义一个函数对象类型，它的返回值和参数都是void*
    //构造函数
    Thread(func_t func,void* args,int number)//number是线程名字，后续int转string
    :_func(func)
    ,_args(args)
    {
        char buffer[NUM];
        snprintf(buffer,sizeof(buffer),"thread-%d",number);
        _name=buffer;
        //线程启动
        Context* ctx=new Context();
        ctx->_this=this;
        ctx->_args=_args;
        int n=pthread_create(&_tid,nullptr,start_routine,ctx);
        assert(n==0);
        (void)n;
    }
    void* run(void* args)
    {
        return _func(args);
    }
    //因为形参有个this指针，所以弄成static
    static void* start_routine(void* args)//这里的args就是 start()的ctx
    {
        Context* ctx=static_cast<Context*>(args);
        void* ret=ctx->_this->run(ctx->_args);
        delete ctx;
        return ret;
    } 
    
    
    void join()
    {
        int n=pthread_join(_tid,nullptr);
        assert(n==0);
        (void)n;
    }
    ~Thread()
    {

    }
    
private:
    std::string _name;//线程的名字
    func_t _func;//线程的回调函数
    void* _args;//喂给线程的参数,不过是用Context类封装一下喂给线程
    pthread_t _tid;//线程ID
};
//异常和if。意料之外
//assert。意料之中。99%概率为真。